#ifndef QISERIALPORTBUFFER_H
#define QISERIALPORTBUFFER_H

#include <QObject>
#include <QSerialPort>
#include "qimsgport.h"

class QiSerialPortBuffer : public QiMSGPort
{
    Q_OBJECT
public:
    explicit QiSerialPortBuffer(QObject *parent = nullptr);
    ~QiSerialPortBuffer()
    {
        disconnect(&_Port, SIGNAL(errorOccurred()), this, SLOT(errorOccurred_slots()));
        close();
    }

    virtual int OpenPortDefault(const QString &name);
    virtual void close(void)
    {
        //disconnect(&_Port, SIGNAL(readyRead()), this, SLOT(recSerialData()));
        _Port.close();
    }
    virtual uint8_t stop(void) { return _stop; }
    virtual void clear(void)
    {
        _Port.clear();
        memset(recv_data, 0, sizeof(recv_data));
        recv_len = 0;
        recv_rindex = 0;
    }
    virtual void flush(void)
    {
        _Port.flush();
    }
    virtual qint64 write(const char *data, qint64 len)
    {
        if(1==_stop) return 0;
        return _Port.write(data, len);
    }
    virtual int read(uint8_t buf[], const int count = 2)
    {
        int len=0;
        //if(_Port.waitForReadyRead(1)) recSerialData();
        if(0==recv_rindex)
        {
            if(_Port.waitForReadyRead(10)) recSerialData();
        }
        if(recv_rindex>=recv_len)
        {
            if(_Port.waitForReadyRead(10)) recSerialData();
        }
        for(len=0; len<count; len++)
        {
            //buf[len] = (uint8_t)recv_data[recv_rindex++];
            buf[len] = static_cast<uint8_t>(recv_data[recv_rindex++]);
        }
        return 0;
    }
    virtual uint8_t read(void)
    {
        //if(_Port.waitForReadyRead(1)) recSerialData();
        if(0==recv_rindex)
        {
            if(_Port.waitForReadyRead(10)) recSerialData();
        }
        if(recv_rindex>=recv_len)
        {
            //clear();
            if(_Port.waitForReadyRead(10)) recSerialData();
        }
        //return (uint8_t)recv_data[recv_rindex++];
        return static_cast<uint8_t>(recv_data[recv_rindex++]);
    }
    virtual int watting_data(const uint32_t timeout)
    {
        uint32_t _time;
        for(_time=0; _time<timeout; _time++)
        {
            _Port.waitForReadyRead(1);
            //if(_Port.waitForReadyRead(1)) break;
            if(_Port.size()>0) break;
            if(0!=stop()) break;
        }
        recSerialData();
        return static_cast<int>(_Port.size());
    }

signals:

public slots:
    void errorOccurred_slots(QSerialPort::SerialPortError error);
    void recSerialData(void)
    {
        QByteArray ba;
        ba = _Port.readAll();
        int count=0;
        const char* datas = ba.constData();
        int len = ba.size();
        for(count=0; count<len; count++)
        {
            if((recv_len+count)>=(sizeof(recv_data))) break;
            recv_data[recv_len+count] = datas[count];
            //qDebug("%02X ", datas[count]);
        }
        recv_len += count;
    }
private:
    uint8_t _stop;
    QSerialPort _Port;

    char recv_data[4096];
    uint16_t recv_len;
    uint16_t recv_rindex;
};

#endif // QISERIALPORTBUFFER_H
